/****************************************************************************
 *
 *  ALi (Shanghai) Corporation, All Rights Reserved. 2004 (C)
 *
 *  File: lib_multiview.c
 *
 *  Description: This file implement the MultiView on M3329
 *         
 *
 *  History:
 *      Date         		Author   		Version  		Comment
 *      ====         	=========       =======  	=======
  ****************************************************************************/
#include <hld/decv/vdec_driver.h>
#include <api/libc/printf.h>
#include <hld/hld_dev.h>
#include <hld/dmx/dmx.h>
#include <hld/dis/VPO.h>
#include <mediatypes.h>
#include <api/libpub/lib_pub.h>
#include <api/libpub/lib_hde.h>
#include <api/libpub/lib_mv.h>
#include <api/libpub/lib_frontend.h>
#include <api/libsi/sie_monitor.h>

/*******************************************************
* macro define
********************************************************/  
#define 	MV_DEBUG PRINTF //libc_printf
#ifdef SPEEDUP_DV //to speed up DV search speed --Michael Xie 2006/2/24
#define  TIMES_FOR_FIRST_PIP	40
#else
#define  TIMES_FOR_FIRST_PIP	80
#endif

#define  GINGA_BUF_LEN	(1920*1080) 
static void *GINGA_BUF_ADDR=NULL;

#define MV_SIM_INVALID_MON_ID	0xFFFFFFFF
static UINT32 MV_PidChg_monitorId = MV_SIM_INVALID_MON_ID;
static UINT32 MV_CAS_PMT_monitorId = MV_SIM_INVALID_MON_ID;//CAS Should monitor PMT to get ECM for CW

/*******************************************************
* extern  declare
********************************************************/
extern BOOL	g_vdec_FirstPIPInChanGot;
extern OSAL_ID libpub_flag_id;
extern void cc_play_channel(UINT32 cmd, struct ft_frontend * ft, struct cc_param * param);
extern void cc_stop_channel(UINT32 cmd, struct cc_es_info *es, struct cc_device_list *dev_list);

/*******************************************************
* struct and variable
********************************************************/
UINT16 l_mv_uIndex[MV_BOX_NUM];	// Modified by Roman
static struct cc_es_info *l_mv_es[MV_BOX_NUM];
static struct cc_device_list *l_mv_dev_list[MV_BOX_NUM];
static struct ft_frontend *l_mv_ft[MV_BOX_NUM];
static struct MVInitPara l_MVinitPara;
static struct MultiViewPara gMvpara;
static struct MVInitPara g_MVinitPara;
   
static UINT8 l_mv_status;
static UINT8 uPrecision;
static UINT8 l_dview_h_precision;
static UINT8 l_dview_v_precision;
static UINT16	l_time_for_first_pip = TIMES_FOR_FIRST_PIP;
static UINT16 	uCurrentActiveIndex = 0;
static BOOL g_bPlayInSpecialWin = FALSE;
static BOOL DrawBoxProcSuccess=FALSE;
static BOOL BoxPlayOk=FALSE;
struct vdec_device*  multi_decv_dev = NULL;
struct vpo_device*  multi_vpo_dev = NULL;

/*******************************************************
* internal function
********************************************************/
/* Set Multiview Flag */
static void set_mv(UINT32 flag)
{
    	osal_flag_set(libpub_flag_id, flag);
}

/* Clear Multiview Flag */
static void clear_mv(UINT32 flag)
{
    	osal_flag_clear(libpub_flag_id, flag);
}

/* Get Multiview Flag */
static BOOL get_mv(UINT32 flag)
{
     	UINT32 flgptn;

    	osal_flag_wait(&flgptn, libpub_flag_id, flag, OSAL_TWF_ORW, 0);
    	if((flgptn & flag) == flag )
    	{
        	return TRUE;
    	}
    	else
    	{
        	return FALSE;
    	}
}
enum
{
	DYN_PID_AV = 1,
	DYN_PID_A,
	DYN_PID_V,
	DYN_PID_A_CNT,
};
void MV_Update_PlayPara(struct MultiViewPara *mvPara)
{
	MEMCPY(&gMvpara, mvPara, sizeof(struct MultiViewPara));
}
static INT32 api_mv_sim_callback(UINT32 param)
{	
	struct sim_cb_param *sim_param = (struct sim_cb_param *)param;

	UINT16 sim_pcr_pid;
	UINT16 sim_video_pid;
	UINT16 sim_audio_pid[P_MAX_AUDIO_NUM];
	UINT8 sim_audio_lang[P_MAX_AUDIO_NUM][3];
	UINT16 sim_audio_count = P_MAX_AUDIO_NUM;

	UINT16 audioPID,ttxPID,subtPID;
	UINT32 audioIdx;
	P_NODE p_node; 
	UINT8 dynamic_pid_type = 0,i;


	if (sim_param->table == MONITE_TB_PMT)
	{
		do
		{
			sim_video_pid = sim_pcr_pid = 8191;
			MEMSET(sim_audio_pid, 8191, P_MAX_AUDIO_NUM);
			MEMSET(sim_audio_lang, 0, P_MAX_AUDIO_NUM*3);

			if (ERR_FAILUE == sim_get_video_pid(sim_param->sim_id, &sim_video_pid))
				break;
			if (ERR_FAILUE == sim_get_audio_info(sim_param->sim_id, sim_audio_pid, sim_audio_lang, (UINT8 *)&sim_audio_count))
				break;
			if (ERR_FAILUE== sim_get_pcr_pid(sim_param->sim_id, &sim_pcr_pid))
				break;
			//if (ERR_FAILUE == sim_get_ecm_pid(sim_param->sim_id,sie_ecm_pids,&max_ecm_cnt))
				//break;
			get_prog_at(l_mv_uIndex[uCurrentActiveIndex], &p_node);
			if(p_node.pmt_pid != sim_param->sec_pid)
			{
				break;
			}

			//MV mode to update video pid, audio pid, ... except ecm pid & emm pid
			if(((sim_video_pid&0x1fff) != p_node.video_pid) 
				||(sim_pcr_pid != p_node.pcr_pid)
				||(sim_audio_count != p_node.audio_count)
				||(MEMCMP(p_node.audio_pid,sim_audio_pid, sizeof(UINT16)*sim_audio_count)!=0))
			{
				// set dynamic_pid_type,for future use...
				if(sim_audio_count == p_node.audio_count)
				{
					if((sim_video_pid&0x1fff) != p_node.video_pid)
					{
						dynamic_pid_type = DYN_PID_AV;
					}
					else
					{
						dynamic_pid_type = DYN_PID_A;
					}
				}
				else
				{
					dynamic_pid_type = DYN_PID_A_CNT;
				}

				if(PROG_TV_MODE ==p_node.av_flag) 
				{
					p_node.video_pid = sim_video_pid&0x1fff;			
					/* maybe video type also change between mpeg2 / h264 */
					if (sim_video_pid & H264_VIDEO_PID_FLAG)
					{
					#if 0 //def PVR_DYNAMIC_PID_CHANGE_TEST
						ap_set_h264_chg_flag(p_node.h264_flag==0?1:0);
					#endif
						p_node.h264_flag = 1;							
					}
					else
					{
					#if 0 //def PVR_DYNAMIC_PID_CHANGE_TEST
						ap_set_h264_chg_flag(p_node.h264_flag==1?1:0);
					#endif
						p_node.h264_flag = 0;
					}
				}
				p_node.pcr_pid = sim_pcr_pid;			
				p_node.audio_count = sim_audio_count;
				MEMCPY(p_node.audio_pid, sim_audio_pid, sizeof(UINT16)*sim_audio_count);
				for (i = 0; i < sim_audio_count; i++)
				{
					get_audio_lang2b(sim_audio_lang[i], (UINT8 *)&p_node.audio_lang[i]);
				}
				modify_prog(p_node.prog_id, &p_node);
				update_data();

				get_prog_at(l_mv_uIndex[uCurrentActiveIndex], &p_node);
				//get_ch_pids(&p_node,&audioPID,&ttxPID,&subtPID,&audioIdx);

				if(l_MVinitPara.AVcallback!=NULL)
				{	
					l_MVinitPara.AVcallback(uCurrentActiveIndex);
					UIMultiviewDrawOneBox(uCurrentActiveIndex);
				}
			}
		}while(0);
	}
}
static void sim_cc_play_channel(UINT32 cmd, struct ft_frontend * ft, struct cc_param * param, UINT16 cur_channel)
{
	P_NODE node;
	struct dmx_device * dmx;
	cc_play_channel(cmd, ft, param);
//	l_mv_es[uActiveIndex]->sim_id = param->es.sim_id;		/* Set SI Monitor ID to Local Variable */

	if (MV_PidChg_monitorId != MV_SIM_INVALID_MON_ID)
	{
		sim_stop_monitor(MV_PidChg_monitorId);
		MV_PidChg_monitorId = MV_SIM_INVALID_MON_ID;
	}

	get_prog_at(cur_channel, &node);
	dmx = (struct dmx_device *)dev_get_by_id(HLD_DEV_TYPE_DMX, 0);	
	
	MV_PidChg_monitorId = sim_start_monitor(dmx, MONITE_TB_PMT, node.pmt_pid, node.prog_number);
	//libc_printf("%s-->%d.\n",__FUNCTION__,MV_PidChg_monitorId);
	if(MV_PidChg_monitorId == MV_SIM_INVALID_MON_ID)
	{
		return -1;//faild to start pmt monitor
		MV_DEBUG("%s-->Faild to start pmt monitor.\n",__FUNCTION__);
	}
	sim_register_ncb(MV_PidChg_monitorId, api_mv_sim_callback);
}
//static void sim_cc_stop_channel(UINT32 cmd, struct ft_frontend * ft, struct cc_param * param)
static void sim_cc_stop_channel(UINT32 cmd, struct cc_es_info *es, struct cc_device_list *dev_list)
{
	cc_stop_channel(cmd, es, dev_list);
	if (MV_PidChg_monitorId != MV_SIM_INVALID_MON_ID)
	{
		sim_stop_monitor(MV_PidChg_monitorId);
		//libc_printf("%s-->%d.\n",__FUNCTION__,MV_PidChg_monitorId);
		MV_PidChg_monitorId = MV_SIM_INVALID_MON_ID;
	}
}

/*API for MV with CA solution:need monitor pmt for CW purpose*/
static UINT32 MV_CA_Notify_Monitor_PMT(UINT16 channel)
{
	P_NODE node;
	struct dmx_device * dmx;
	UINT32 ret=MV_SIM_INVALID_MON_ID;
	get_prog_at(channel, &node);
	dmx = (struct dmx_device *)dev_get_by_id(HLD_DEV_TYPE_DMX, 0);
	if(node.ca_mode)
		ret=sim_start_monitor(dmx, MONITE_TB_PMT, node.pmt_pid, node.prog_number);
	//libc_printf("%s-->%d.\n",__FUNCTION__,ret);
	return ret;
}

static void MV_CA_Stop_Monitor_PMT(void)
{
	if (MV_CAS_PMT_monitorId != MV_SIM_INVALID_MON_ID)
	{
		sim_stop_monitor(MV_CAS_PMT_monitorId);
		//ibc_printf("%s-->%d.\n",__FUNCTION__,MV_CAS_PMT_monitorId);
		MV_CAS_PMT_monitorId = MV_SIM_INVALID_MON_ID;
	}
}
void MuliView_Config_WinPara(struct MPSource_CallBack *vMPCallBack, struct PIPSource_CallBack *vPIPCallBack)
{
	struct vp_win_config_para win_para;
	if(sys_ic_get_chip_id() == ALI_S3811 || sys_ic_get_chip_id() == ALI_S3503 || sys_ic_get_chip_id() == ALI_S3821)
	{
      #if 0
		 win_para.source_number = 2;
        win_para.control_source_index = 0;
        win_para.window_number = 2;
        win_para.source_info[0].attach_source_index = 1;
        win_para.source_info[0].src_callback.request_callback = (T_Request_ext)(vPIPCallBack->RequestCallback);//(T_Request)(vMPCallBack.RequestCallback);//
        win_para.source_info[0].src_callback.release_callback = (T_Release_ext)(vPIPCallBack->ReleaseCallback);//(T_Release)(vMPCallBack.ReleaseCallback);//
        win_para.source_info[0].src_callback.vblanking_callback= NULL;//vMPCallBack.vblanking_callback;
        win_para.source_info[0].src_module_devide_handle = multi_decv_dev;
        win_para.source_info[0].src_path_index = 1;        
        win_para.window_parameter[0].source_index = 0;
        win_para.window_parameter[0].display_layer = VPO_LAYER_MAIN;
        win_para.window_parameter[0].rect.src_rect.uStartX = 0;
        win_para.window_parameter[0].rect.src_rect.uStartY = 0;
        win_para.window_parameter[0].rect.src_rect.uWidth = PICTURE_WIDTH;
        win_para.window_parameter[0].rect.src_rect.uHeight = PICTURE_HEIGHT;	
        win_para.window_parameter[0].rect.dst_rect.uStartX = 0;
        win_para.window_parameter[0].rect.dst_rect.uStartY = 0;
        win_para.window_parameter[0].rect.dst_rect.uWidth = SCREEN_WIDTH;
        win_para.window_parameter[0].rect.dst_rect.uHeight = SCREEN_HEIGHT;
        win_para.source_info[1].attach_source_index = 1;
        win_para.source_info[1].src_callback.request_callback = (T_Request)(vMPCallBack->RequestCallback);//(T_Request_ext)(vPIPCallBack.RequestCallback);//
        win_para.source_info[1].src_callback.release_callback = (T_Release)(vMPCallBack->ReleaseCallback);//(T_Release_ext)(vPIPCallBack.ReleaseCallback);//
        win_para.source_info[1].src_callback.vblanking_callback= vMPCallBack->vblanking_callback;
        win_para.source_info[1].src_module_devide_handle = multi_decv_dev;
        win_para.source_info[1].src_path_index = 0;        
        win_para.window_parameter[1].source_index = 1;
        win_para.window_parameter[1].display_layer = VPO_LAYER_AUXP;
        win_para.window_parameter[1].rect.src_rect.uStartX = 0;
        win_para.window_parameter[1].rect.src_rect.uStartY = 0;
        win_para.window_parameter[1].rect.src_rect.uWidth = PICTURE_WIDTH;
        win_para.window_parameter[1].rect.src_rect.uHeight = PICTURE_HEIGHT;	
        win_para.window_parameter[1].rect.dst_rect.uStartX = 0;
        win_para.window_parameter[1].rect.dst_rect.uStartY = 0;
        win_para.window_parameter[1].rect.dst_rect.uWidth = SCREEN_WIDTH;
        win_para.window_parameter[1].rect.dst_rect.uHeight = SCREEN_HEIGHT;
        #endif
        win_para.source_number = 2;
        win_para.control_source_index = 0;
        win_para.window_number = 2;
        win_para.source_info[0].attach_source_index = 1;
        win_para.source_info[0].src_callback.request_callback = (T_Request)(vMPCallBack->RequestCallback);//(T_Request_ext)(vPIPCallBack->RequestCallback);//
        win_para.source_info[0].src_callback.release_callback = (T_Release)(vMPCallBack->ReleaseCallback);//(T_Release_ext)(vPIPCallBack->ReleaseCallback);//
        win_para.source_info[0].src_callback.vblanking_callback= vMPCallBack->vblanking_callback;//NULL;//
        win_para.source_info[0].src_module_devide_handle = multi_decv_dev;
        win_para.source_info[0].src_path_index = 0;        
        win_para.window_parameter[0].source_index = 0;///1;//0;
        win_para.window_parameter[0].display_layer = VPO_LAYER_MAIN;
        win_para.window_parameter[0].rect.src_rect.uStartX = 0;
        win_para.window_parameter[0].rect.src_rect.uStartY = 0;
        win_para.window_parameter[0].rect.src_rect.uWidth = PICTURE_WIDTH;
        win_para.window_parameter[0].rect.src_rect.uHeight = PICTURE_HEIGHT;	
        win_para.window_parameter[0].rect.dst_rect.uStartX = 0;
        win_para.window_parameter[0].rect.dst_rect.uStartY = 0;
        win_para.window_parameter[0].rect.dst_rect.uWidth = SCREEN_WIDTH;
        win_para.window_parameter[0].rect.dst_rect.uHeight = SCREEN_HEIGHT;
        
        win_para.source_info[1].attach_source_index = 1;
        win_para.source_info[1].src_callback.request_callback = (T_Request_ext)(vPIPCallBack->RequestCallback);//(T_Request)(vMPCallBack->RequestCallback);//
        win_para.source_info[1].src_callback.release_callback = (T_Release_ext)(vPIPCallBack->ReleaseCallback);//(T_Release)(vMPCallBack->ReleaseCallback);//
        win_para.source_info[1].src_callback.vblanking_callback= NULL;//vMPCallBack->vblanking_callback;
        win_para.source_info[1].src_module_devide_handle = multi_decv_dev;
        win_para.source_info[1].src_path_index = 1;        
        win_para.window_parameter[1].source_index = 1;///0;///1;
        win_para.window_parameter[1].display_layer = VPO_LAYER_AUXP;
        win_para.window_parameter[1].rect.src_rect.uStartX = 0;
        win_para.window_parameter[1].rect.src_rect.uStartY = 0;
        win_para.window_parameter[1].rect.src_rect.uWidth = PICTURE_WIDTH;
        win_para.window_parameter[1].rect.src_rect.uHeight = PICTURE_HEIGHT;	
        win_para.window_parameter[1].rect.dst_rect.uStartX = 0;
        win_para.window_parameter[1].rect.dst_rect.uStartY = 0;
        win_para.window_parameter[1].rect.dst_rect.uWidth = SCREEN_WIDTH;
        win_para.window_parameter[1].rect.dst_rect.uHeight = SCREEN_HEIGHT;

        vpo_config_source_window(multi_vpo_dev, &win_para);
	}
	else
	{
		win_para.source_number = 1;
		win_para.control_source_index = 0;
		win_para.source_info[0].attach_source_index = 1;
		win_para.source_info[0].src_callback.request_callback = (T_Request)(vMPCallBack->RequestCallback);//(T_PIPRequest)(vPIPCallBack.RequestCallback);
		win_para.source_info[0].src_callback.release_callback = (T_Release)(vMPCallBack->ReleaseCallback);//(T_PIPRelease)(vPIPCallBack.ReleaseCallback);
		win_para.source_info[0].src_callback.vblanking_callback= NULL;
		win_para.source_info[0].src_module_devide_handle = multi_decv_dev;
		win_para.source_info[0].src_path_index = 0;
		win_para.window_number = 2;
		win_para.window_parameter[0].source_index = 0;
		win_para.window_parameter[0].display_layer = VPO_LAYER_GMA1;
		win_para.window_parameter[0].rect.src_rect.uStartX = 0;
		win_para.window_parameter[0].rect.src_rect.uStartY = 0;
		win_para.window_parameter[0].rect.src_rect.uWidth = PICTURE_WIDTH;
		win_para.window_parameter[0].rect.src_rect.uHeight = PICTURE_HEIGHT;	
		win_para.window_parameter[0].rect.dst_rect.uStartX = 0;
		win_para.window_parameter[0].rect.dst_rect.uStartY = 0;
		win_para.window_parameter[0].rect.dst_rect.uWidth = SCREEN_WIDTH;
		win_para.window_parameter[0].rect.dst_rect.uHeight = SCREEN_HEIGHT;

		win_para.control_source_index = 0;
		win_para.source_info[1].attach_source_index = 1;
		win_para.source_info[1].src_callback.request_callback = (T_PIPRequest)(vPIPCallBack->RequestCallback);
		win_para.source_info[1].src_callback.release_callback = (T_PIPRelease)(vPIPCallBack->ReleaseCallback);
		win_para.source_info[1].src_callback.vblanking_callback= NULL;
		win_para.source_info[1].src_module_devide_handle = multi_decv_dev;
		win_para.source_info[1].src_path_index = 0;
		win_para.window_number = 2;
		win_para.window_parameter[1].source_index = 1;
		win_para.window_parameter[1].display_layer = VPO_LAYER_MAIN;
		win_para.window_parameter[1].rect.src_rect.uStartX = 0;
		win_para.window_parameter[1].rect.src_rect.uStartY = 0;
		win_para.window_parameter[1].rect.src_rect.uWidth = PICTURE_WIDTH;
		win_para.window_parameter[1].rect.src_rect.uHeight = PICTURE_HEIGHT;	
		win_para.window_parameter[1].rect.dst_rect.uStartX = 0;
		win_para.window_parameter[1].rect.dst_rect.uStartY = 0;
		win_para.window_parameter[1].rect.dst_rect.uWidth = SCREEN_WIDTH;
		win_para.window_parameter[1].rect.dst_rect.uHeight = SCREEN_HEIGHT;
		vpo_config_source_window(multi_vpo_dev, &win_para);
	}
}


/* Play One Special Box */
//static BOOL MultiView_Play_ActiveBox(struct Position *pPos, struct cc_es_info* es, struct ft_frontend* ft, struct cc_device_list* dev_list,UINT32 BoxStatus,struct VDecPIPInfo *PIPInitInfo)
//MultiView_Play_ActiveBox(&l_MVinitPara.tMPipBoxPosi[uActiveIndex], l_mv_es[uActiveIndex], l_mv_ft[uActiveIndex], l_mv_dev_list[uActiveIndex], boxStatus, &PIPInitInfo);
static BOOL MultiView_Play_ActiveBox(UINT16 uActiveIndex ,UINT32 BoxStatus,struct VDecPIPInfo *PIPInitInfo)
{
		struct MPSource_CallBack MPCallBack;
		struct PIPSource_CallBack PIPCallBack;
		struct Rect DstRect;
		UINT32 cmd=0;
		struct cc_param param;
		struct VDec_StatusInfo vParam;
		UINT32 count=0;

		
		if(get_mv_cancel())
		{
			//BoxStatus = BOX_PLAY_ABORT;
			return FALSE;
		}

		if(BoxStatus!=BOX_PLAY_ABORT)
		{
			struct Rect SrcRect = {0,0,720,2880};

            vpo_win_onoff(multi_vpo_dev, FALSE);
            
			//vpo_win_onoff_ext(multi_vpo_dev,0,VPO_LAYER_AUXP);
			MEMCPY(&(param.es), l_mv_es[uActiveIndex], sizeof(struct cc_es_info));
			MEMCPY(&(param.dev_list), l_mv_dev_list[uActiveIndex], sizeof(struct cc_device_list));
			cmd &= ~(CC_CMD_CLOSE_VPO|CC_CMD_FILL_FB);

			if(g_bPlayInSpecialWin)//if N+1 MODE,need specify the Play window positon
			{
				DstRect.uHeight = (l_MVinitPara.PlayWin.uHeight);
				DstRect.uWidth = l_MVinitPara.PlayWin.uWidth;
				DstRect.uStartX = l_MVinitPara.PlayWin.uStartX;
				DstRect.uStartY =(l_MVinitPara.PlayWin.uStartY);
			}
			else
			{
				DstRect.uStartX = (l_MVinitPara.tMPipBoxPosi[uActiveIndex].uX);
				DstRect.uStartY = (l_MVinitPara.tMPipBoxPosi[uActiveIndex].uY);
				DstRect.uWidth = (l_MVinitPara.tMPipSize.uWidth);
				DstRect.uHeight = (l_MVinitPara.tMPipSize.uHeight);
			}
			
			//re-get the right device
			if(((param.es.v_pid)& H264_VIDEO_PID_FLAG) == H264_VIDEO_PID_FLAG)
				multi_decv_dev = (struct vdec_device *)dev_get_by_name("DECV_AVC_0");
			else
				multi_decv_dev = (struct vdec_device *)dev_get_by_type(NULL, HLD_DEV_TYPE_DECV);


          if((DstRect.uHeight<1440)&&(DstRect.uWidth<360))
              vdec_io_control(multi_decv_dev,VDEC_IO_SET_MULTIVIEW_WIN,TRUE);
          else
              vdec_io_control(multi_decv_dev,VDEC_IO_SET_MULTIVIEW_WIN,FALSE);

			//cc_play_channel(cmd, l_mv_ft[uActiveIndex], &param);
			sim_cc_play_channel(cmd, l_mv_ft[uActiveIndex], &param,l_mv_uIndex[uActiveIndex]);

			vdec_set_output(multi_decv_dev,(enum VDecOutputMode)MULTI_VIEW_MODE, PIPInitInfo, &MPCallBack, &PIPCallBack);		
			MuliView_Config_WinPara(&MPCallBack,&PIPCallBack);

			vpo_zoom_ext(multi_vpo_dev,&SrcRect, &DstRect,VPO_LAYER_MAIN);//VPO_LAYER_AUXP);

			vdec_io_control(multi_decv_dev,VDEC_IO_GET_STATUS,(UINT32)&vParam);

//!Only viewable window update GINGA BUF(set AUX-Pic Layer transparent) 
			while((!vParam.uFirstPicShowed)&&(count<300))
			{
				if(get_mv_cancel())
					break;
				osal_task_sleep(10);
				vdec_io_control(multi_decv_dev, VDEC_IO_GET_STATUS, (UINT32)&vParam);
				count++;
			}
			if(vParam.uFirstPicShowed)
			{
                if(sys_ic_get_chip_id() == ALI_S3811)
				    vpo_ioctl(multi_vpo_dev, VPO_IO_UPDATE_GINGA, 0);
			}
			else
			{
				MV_DEBUG("Error,%s:uFirstPicShowed timeout,not update GINGABUF.\n",__FUNCTION__);
			}
//!end			
			BoxPlayOk=TRUE;
		}
    return TRUE;
}


//Fill picture to Specified Box 
//static BOOL MW_SwitchPIPWin(struct Position *pPos, struct cc_es_info* es, struct ft_frontend* ft, struct cc_device_list* dev_list, UINT32 uBoxStatus, BOOL spe_win_flg,UINT8 BoxIndex)
static BOOL MW_SwitchPIPWin(struct cc_es_info* es, struct ft_frontend* ft, struct cc_device_list* dev_list, UINT32 uBoxStatus, BOOL spe_win_flg,UINT8 BoxIndex)
{
	UINT8 ret_val;
	UINT16 counter=0;
	UINT8 unlockTimes=0;
	UINT8 lock= 0;
	UINT32 cmd = 0;
	struct cc_param param;
	
	struct Rect PipWin; 
	struct MPSource_CallBack MPCallBack;
	struct PIPSource_CallBack PIPCallBack;
	struct VDecPIPInfo  PIPInitInfo;
	struct VDec_StatusInfo Param;
	struct back_pip_info PipInfo;
	struct Rect SrcRect = {0,0,720,2880};
	UINT8 scramble_type=0;
	RET_CODE dmx_state = RET_FAILURE;

	if(get_mv_cancel())
	{
		return FALSE;
	}

	if(uBoxStatus!=BOX_PLAY_ABORT)
	{
        vpo_win_onoff(multi_vpo_dev, FALSE);
		//2Configure the position of output box from VP
    	if(spe_win_flg)
		{
				PipWin.uHeight = (l_MVinitPara.PlayWin.uHeight);
				PipWin.uWidth = l_MVinitPara.PlayWin.uWidth;
				PipWin.uStartX = l_MVinitPara.PlayWin.uStartX;
				PipWin.uStartY =(l_MVinitPara.PlayWin.uStartY);
	    }
		else
		{
				PipWin.uHeight = (l_MVinitPara.tMPipSize.uHeight);
				PipWin.uWidth = l_MVinitPara.tMPipSize.uWidth;
				PipWin.uStartX = l_MVinitPara.tMPipBoxPosi[BoxIndex].uX;
				PipWin.uStartY = (l_MVinitPara.tMPipBoxPosi[BoxIndex].uY);
		}

// Play this Box
		//vpo_win_onoff_ext(multi_vpo_dev,0,VPO_LAYER_AUXP);
		MEMCPY(&(param.es), es, sizeof(struct cc_es_info));
		MEMCPY(&(param.dev_list), dev_list, sizeof(struct cc_device_list));
		cmd &= ~(CC_CMD_CLOSE_VPO|CC_CMD_FILL_FB);
    	//cc_play_channel(cmd, ft, &param);	/* Get SI Monitor ID in this function */
		//es->sim_id = param.es.sim_id;		/* Set SI Monitor ID to Local Variable */

		//re-get the right device
		if(((param.es.v_pid)& H264_VIDEO_PID_FLAG) == H264_VIDEO_PID_FLAG)
			multi_decv_dev = (struct vdec_device *)dev_get_by_name("DECV_AVC_0");
		else
			multi_decv_dev = (struct vdec_device *)dev_get_by_type(NULL, HLD_DEV_TYPE_DECV);
		if((PipWin.uHeight<1440)&&(PipWin.uWidth<360))
			vdec_io_control(multi_decv_dev,VDEC_IO_SET_MULTIVIEW_WIN,TRUE);
		else
			vdec_io_control(multi_decv_dev,VDEC_IO_SET_MULTIVIEW_WIN,FALSE);
		#if(defined( SUPPORT_CAS9) ||defined(SUPPORT_CAS7))
			MV_CAS_PMT_monitorId=MV_CA_Notify_Monitor_PMT(l_mv_uIndex[BoxIndex]);
		#endif
		cc_play_channel(cmd, ft, &param);
//		es->sim_id = param.es.sim_id;		/* Set SI Monitor ID to Local Variable */

		ret_val=vdec_set_output(multi_decv_dev,(enum VDecOutputMode)MULTI_VIEW_MODE, &PIPInitInfo, &MPCallBack, &PIPCallBack);		

		if (ret_val != RET_SUCCESS)
		{
			MV_DEBUG("MV ---VDec_SetOutput return false.\n");
		}

		MuliView_Config_WinPara(&MPCallBack,&PIPCallBack);
		vpo_zoom_ext(multi_vpo_dev,&SrcRect, &PipWin,VPO_LAYER_MAIN);//VPO_LAYER_AUXP);
		vdec_io_control(multi_decv_dev,VDEC_IO_GET_STATUS,(UINT32)&Param);
		
		if((VDEC_DECODING==Param.uCurStatus)
		    //&&!((l_MVinitPara.tMPipBoxPosi[BoxIndex].uX==l_MVinitPara.tMPipBoxPosi[gMvpara.uBoxNum-1].uX)
			//&&(l_MVinitPara.tMPipBoxPosi[BoxIndex].uY==l_MVinitPara.tMPipBoxPosi[gMvpara.uBoxNum-1].uY)
			//&&(uCurrentActiveIndex==(gMvpara.uBoxNum-1)))
			)
		{
			while(!Param.uFirstPicShowed)
			{
				if(get_mv_cancel())
					return FALSE;
				osal_task_sleep(10);
				vdec_io_control(multi_decv_dev, VDEC_IO_GET_STATUS, (UINT32)&Param);
				counter++;
					
				if(counter ==(l_time_for_first_pip*7))//reach the longest time
				{
					break;
				} 
				if(counter>l_time_for_first_pip)
				{ 
					nim_get_lock((struct nim_device*)dev_get_by_id(HLD_DEV_TYPE_NIM, 0), &lock);
					if(lock == 0)
					{
						unlockTimes++;
					}
					else
						unlockTimes=0;
					if(unlockTimes>(l_time_for_first_pip/2))
					{
						MV_DEBUG("%s:leave with unlock>>Counter:%d\n",__FUNCTION__,counter);
						break;		
					}
				} 
				
				struct dmx_device *dmx;
				dmx = (struct dmx_device *)dev_get_by_id(HLD_DEV_TYPE_DMX, 0);
                dmx_state = dmx_io_control(dmx, IS_AV_SCRAMBLED, (UINT32)&scramble_type);
                // the channel is scrambled
                if((RET_SUCCESS==dmx_state)
                    &&((scramble_type & (VDE_TS_SCRBL|VDE_PES_SCRBL | VDE_STR_INVALID)) != 0)
                            &&(counter>=(3*l_time_for_first_pip)))
				{
					MV_DEBUG("%s:leave with scrambled>>Counter:%d\n",__FUNCTION__,counter);
					break;
				} 
				if(counter %(l_time_for_first_pip*2)==0&&counter>=l_time_for_first_pip)//reset qpsk
				{ 
					//cc_reset_qpsk(0);
					MV_DEBUG("MV___MW_SwitchPIPWin reset qpsk>>>>>>>>>%d>>>>>>>>.\n",counter);				
				} 
			}	
			if(Param.uFirstPicShowed)
			{
                if(sys_ic_get_chip_id() == ALI_S3811)
				    vpo_ioctl(multi_vpo_dev, VPO_IO_UPDATE_GINGA, 0);
				
				PipInfo.full_screen_height=1080;
				PipInfo.full_screen_width=1920;
				PipInfo.left_x=l_MVinitPara.puBoxPosi[BoxIndex].uX;
				PipInfo.left_y=l_MVinitPara.puBoxPosi[BoxIndex].uY;
				PipInfo.window_height=l_MVinitPara.tPipSize.uHeight;
				PipInfo.window_width=l_MVinitPara.tPipSize.uWidth;
				vdec_stop(multi_decv_dev,FALSE,FALSE);
				vdec_io_control(multi_decv_dev, VDEC_IO_FILL_BG_VIDEO, (UINT32)&PipInfo);
				osal_task_sleep(50);//wait for the DE  switch buffer,avoid flash screen when change window
				
                if(sys_ic_get_chip_id() == ALI_S3811)
                    vpo_ioctl(multi_vpo_dev, VPO_IO_UPDATE_GINGA, 1);
				
	            MV_DEBUG("%s-->#Got the(%d,%d) box's picture,Counter=%d.\n",__FUNCTION__,
	                l_MVinitPara.puBoxPosi[BoxIndex].uX,l_MVinitPara.puBoxPosi[BoxIndex].uY);
			}
			else
			{
                MV_DEBUG("%s-->#Not get the(%d,%d) box's picture,Counter=%d.\n",__FUNCTION__,
                    l_MVinitPara.puBoxPosi[BoxIndex].uX,l_MVinitPara.puBoxPosi[BoxIndex].uY);
			}
		}
		else
		{
		    MV_DEBUG("%s->VDEC NOT DECODING\n",__FUNCTION__);
		}
	}
	return TRUE;
}

static RET_CODE MultiView_Enter(UINT32 cmd, struct MultiViewPara *mvPara)
{
	UINT8 i;
	UINT8 ret_val,mv_ret_val;
	UINT16* pProg=mvPara->uProgInfo; 
	UINT32 boxStatus = BOX_PLAY_NORMAL;
	struct multiview_info muti_info;
	struct VDecPIPInfo  PIPInitInfo;
	struct MPSource_CallBack MPCallBack;
	struct PIPSource_CallBack PIPCallBack;
	
	MV_DEBUG("MV-->MultiView_Enter\n");

    if(sys_ic_get_chip_id() == ALI_S3811)
    {
    	if(GINGA_BUF_ADDR == NULL)
    	    GINGA_BUF_ADDR = (void*)MALLOC(GINGA_BUF_LEN);
    	if(GINGA_BUF_ADDR)
    	{
    		vpo_ioctl((struct vpo_device *)dev_get_by_type(NULL, HLD_DEV_TYPE_DIS), VPO_IO_SET_MULTIVIEW_BUF, GINGA_BUF_ADDR);
    	}
    	else
    	{
    		MV_DEBUG("ERROR,MV MALLOC GINGA BUF FAIL\n");
    	}
    }
    

	// Disable Subtitle
#if (SUBTITLE_ON == 1)
	subt_enable(FALSE);
#endif
#if (TTX_ON ==1)
        ttx_enable(FALSE);
#endif
#ifndef _BUILD_OTA_E_
    epg_off_ext();
#endif

	//set_mv(LIBPUB_FLG_MV_ENTER);
	//If View Mode is Multiview, then Stop the Current Channel of Last Multiview
	if(hde_get_mode() == VIEW_MODE_MULTI)
	{
		sim_cc_stop_channel(cmd, l_mv_es[uCurrentActiveIndex], l_mv_dev_list[uCurrentActiveIndex]);
		MV_CA_Stop_Monitor_PMT();
	}
	// Set Multiview Status
	l_mv_status = MV_ACTIVE | MV_SCAN_SCREEN | MV_SCAN_BOX;

	MEMCPY(&gMvpara, mvPara, sizeof(struct MultiViewPara));
	for(i=0;i<gMvpara.uBoxNum;i++)
	{
		l_mv_uIndex[i]=*pProg;
		pProg++;
	}
	uCurrentActiveIndex = gMvpara.uBoxActiveIdx-1;

	//check the decoder device of the first box 
	if(((l_mv_es[0]->v_pid)& H264_VIDEO_PID_FLAG) == H264_VIDEO_PID_FLAG)
		multi_decv_dev = (struct vdec_device *)dev_get_by_name("DECV_AVC_0");
	else
		multi_decv_dev = (struct vdec_device *)dev_get_by_type(NULL, HLD_DEV_TYPE_DECV);
	multi_vpo_dev = (struct vpo_device *)dev_get_by_type(NULL, HLD_DEV_TYPE_DIS);

	//MEMSET for GINGA_BUF
	if(sys_ic_get_chip_id() == ALI_S3811)
    {
	    vpo_ioctl(multi_vpo_dev, VPO_IO_FILL_GINGA_BUF, 1);
	}

    if(sys_ic_get_chip_id() == ALI_S3503 || sys_ic_get_chip_id() == ALI_S3821)
    {
        vpo_ioctl(multi_vpo_dev, VPO_IO_SET_LAYER_ORDER, AUXP_MP_GMAS_GMAF);
    }
	//3Switch to PIP
	if(hde_get_mode() != VIEW_MODE_MULTI)
	{
		// Set Multiview Mode
		hde_set_mode(VIEW_MODE_MULTI);
		PIPInitInfo.pipStaPos.uX=l_MVinitPara.puBoxPosi[0].uX;
		PIPInitInfo.pipStaPos.uY=l_MVinitPara.puBoxPosi[0].uY;
		PIPInitInfo.mpSize.uHeight=l_MVinitPara.tMpSize.uHeight;
		PIPInitInfo.mpSize.uWidth=l_MVinitPara.tMpSize.uWidth;
		PIPInitInfo.pipSize.uHeight=l_MVinitPara.tPipSize.uHeight;
		PIPInitInfo.pipSize.uWidth=l_MVinitPara.tPipSize.uWidth;

		PIPInitInfo.bUseBgColor=1;
		PIPInitInfo.bgColor.uCb=0x80;
		PIPInitInfo.bgColor.uCr=0x80;
		PIPInitInfo.bgColor.uY=0x10;
		PIPInitInfo.para.window_height=l_MVinitPara.tPipSize.uHeight;
		PIPInitInfo.para.window_width=l_MVinitPara.tPipSize.uWidth;
		PIPInitInfo.para.multi_view_buf_addr=gMvpara.multi_view_buf_addr;
		PIPInitInfo.para.multi_view_buf_size=gMvpara.multi_view_buf_size;

		muti_info.full_screen_height = 1080;
		muti_info.full_screen_width = 1920;
		muti_info.multiview_buf = gMvpara.multi_view_buf_addr;
		
		vdec_io_control((struct vdec_device *)dev_get_by_type(NULL, HLD_DEV_TYPE_DECV),
		                VDEC_IO_GET_MULTIVIEW_BUF,(UINT32)&muti_info);
		vdec_io_control((struct vdec_device *)dev_get_by_name("DECV_AVC_0"),
		                VDEC_IO_GET_MULTIVIEW_BUF,(UINT32)&muti_info);

//Stop Current channel
		cmd |= (CC_CMD_CLOSE_VPO | CC_CMD_FILL_FB);
		cc_stop_channel(cmd, l_mv_es[uCurrentActiveIndex], l_mv_dev_list[uCurrentActiveIndex]);
		osal_task_sleep(30);
		ret_val=vdec_set_output(multi_decv_dev,(enum VDecOutputMode)MULTI_VIEW_MODE, &PIPInitInfo, &MPCallBack, &PIPCallBack);		
		if (ret_val != RET_SUCCESS)
		{
			//avc device should be open and initialize	first		
			h264_decoder_select(1, 0);
			ret_val=vdec_set_output(multi_decv_dev,(enum VDecOutputMode)MULTI_VIEW_MODE, &PIPInitInfo, &MPCallBack, &PIPCallBack);		
			if(ret_val != RET_SUCCESS)
			{	
				MV_DEBUG("MV ---VDec_SetOutput error.\n");
				SDBBP();
			}
		}
		vdec_io_control(multi_decv_dev, VDEC_IO_BG_FILL_BLACK, 0);
		MuliView_Config_WinPara(&MPCallBack,&PIPCallBack);
	}
	else
	{
		vdec_io_control(multi_decv_dev, VDEC_IO_BG_FILL_BLACK, 0);
		osal_task_sleep(100);
	}

//1//STEP1:FILL Picture to all Boxes one by one
	if(l_MVinitPara.callback!=NULL)
			boxStatus=l_MVinitPara.callback(BOX_SCAN_START);
	for(i=0;i<gMvpara.uBoxNum;i++)
	{
		boxStatus=BOX_PLAY_NORMAL;
		if(l_MVinitPara.callback!=NULL)
			boxStatus=l_MVinitPara.callback(i);
		
		cmd &= ~ (CC_CMD_CLOSE_VPO | CC_CMD_FILL_FB);
		if( i != 0)
		{
			cc_stop_channel(cmd, l_mv_es[i - 1], l_mv_dev_list[i - 1]);
			MV_CA_Stop_Monitor_PMT();
		}
		
		mv_ret_val=TRUE;
		//ret_val = MW_SwitchPIPWin(&l_MVinitPara.puBoxPosi[i], l_mv_es[i], l_mv_ft[i], l_mv_dev_list[i], boxStatus, g_bPlayInSpecialWin);
		mv_ret_val = MW_SwitchPIPWin(l_mv_es[i], l_mv_ft[i], l_mv_dev_list[i], boxStatus, g_bPlayInSpecialWin,i);

		if(l_MVinitPara.callback!=NULL)
			l_MVinitPara.callback(i+BOX_FINISHED);
		if(mv_ret_val==FALSE)
		{
			MV_DEBUG("MV-->receive a message to quit.\n");
			break;
		}
	}

 	if((i!=gMvpara.uBoxNum)||(get_mv_cancel()))
	{
  		cc_stop_channel(cmd, l_mv_es[i>0?(i-1):i], l_mv_dev_list[i>0?(i-1):i]);
		MV_CA_Stop_Monitor_PMT();
		l_mv_status=MV_ACTIVE;
		MV_DEBUG("MV-->receive a message to return:%d.\n",i);
		return RET_FAILURE;
	}
	l_mv_status=MV_ACTIVE|MV_SCAN_SCREEN;
	osal_task_sleep(1000);//this may need some information from Ch_Chg and VDEC		

//1STEP2: Play the Active Box

	//if(gMvpara.uBoxNum != (gMvpara.uBoxActiveIdx)) 
	//{
		cc_stop_channel(cmd, l_mv_es[i - 1], l_mv_dev_list[i - 1]);
		MV_CA_Stop_Monitor_PMT();
        
		if(l_MVinitPara.callback!=NULL)
			boxStatus=l_MVinitPara.callback(uCurrentActiveIndex);
                
		mv_ret_val = MultiView_Play_ActiveBox(uCurrentActiveIndex, 1, &PIPInitInfo);

		if(l_MVinitPara.callback!=NULL)
			l_MVinitPara.callback(uCurrentActiveIndex+BOX_FINISHED+BOX_FOCUS);

		if(mv_ret_val==FALSE)
		{
			l_mv_status=MV_ACTIVE;
			return RET_FAILURE;
		}
	//}

	l_mv_status=MV_ACTIVE;
	MV_DEBUG("MV_MODE:%d,MultiView_Enter success!\n",gMvpara.MVMode);
	return RET_SUCCESS;
}

/* Exit Multiview */
static RET_CODE MultiView_Exit()
{
	UINT8 ret_val;
	struct VDecPIPInfo  PIPInitInfo;
	struct MPSource_CallBack MPCallBack;
	struct PIPSource_CallBack PIPCallBack;
	BOOL bVdecStopped;
	UINT32 cmd = 0;
	MV_DEBUG("%s-->\n",__FUNCTION__);

    if(sys_ic_get_chip_id() == ALI_S3503|| sys_ic_get_chip_id() == ALI_S3821)
    {
        vpo_ioctl(multi_vpo_dev, VPO_IO_SET_LAYER_ORDER, MP_GMAS_GMAF_AUXP);
    }
	if(hde_get_mode() != VIEW_MODE_MULTI)
	{
		return RET_FAILURE;
	}
	else
	{
		if(((l_mv_es[uCurrentActiveIndex]->v_pid)& H264_VIDEO_PID_FLAG) == H264_VIDEO_PID_FLAG)
			multi_decv_dev = (struct vdec_device *)dev_get_by_name("DECV_AVC_0");
		else
			multi_decv_dev = (struct vdec_device *)dev_get_by_type(NULL, HLD_DEV_TYPE_DECV);

        if(sys_ic_get_chip_id() == ALI_S3811)
		    vpo_ioctl(multi_vpo_dev, VPO_IO_UPDATE_GINGA, 1);
		
		vdec_io_control(multi_decv_dev, VDEC_IO_BG_FILL_BLACK, 0);
		vpo_win_onoff_ext(multi_vpo_dev, FALSE, VPO_LAYER_M);
		vpo_win_onoff_ext(multi_vpo_dev, FALSE, VPO_LAYER_AUXP);
		osal_task_sleep(100);
		cmd |= (CC_CMD_CLOSE_VPO | CC_CMD_FILL_FB);
		sim_cc_stop_channel(cmd, l_mv_es[uCurrentActiveIndex], l_mv_dev_list[uCurrentActiveIndex]);
		MV_CA_Stop_Monitor_PMT();
	
		ret_val=vdec_set_output(multi_decv_dev,(enum VDecOutputMode)MP_MODE, &PIPInitInfo, &MPCallBack, &PIPCallBack);
		
		vpo_win_mode(multi_vpo_dev, VPO_MAINWIN, &MPCallBack, &PIPCallBack);
		osal_task_sleep(100);
		vpo_win_onoff_ext(multi_vpo_dev, FALSE, VPO_LAYER_AUXP);
		osal_task_sleep(50);
		vdec_io_control((struct vdec_device *)dev_get_by_name("DECV_AVC_0"),VDEC_IO_SET_MULTIVIEW_WIN,FALSE);
		vdec_io_control((struct vdec_device *)dev_get_by_type(NULL, HLD_DEV_TYPE_DECV),VDEC_IO_SET_MULTIVIEW_WIN,FALSE);

		if(GINGA_BUF_ADDR && sys_ic_get_chip_id() == ALI_S3811)
		{
			FREE(GINGA_BUF_ADDR);
			GINGA_BUF_ADDR = NULL;
		}
		hde_set_mode(VIEW_MODE_FULL);
#if (defined(SUBTITLE_ON) && SUBTITLE_ON == 1)
		subt_enable(TRUE);
#endif
#if (TTX_ON ==1)
        ttx_enable(TRUE);
#endif
#ifndef _BUILD_OTA_E_
        epg_reset();
        epg_on_ext();
#endif    
   		l_mv_status=MV_IDLE;
		return RET_SUCCESS;
	}
}

static BOOL MV_StoreLastPicture(void)
{
		struct VDec_StatusInfo Param;
		UINT16 counter=0;
		UINT8 unlockTimes=0;
		UINT8 lock= 0;
		struct back_pip_info PipInfo;
		BOOL IsPlayNormal=TRUE;
		UINT8 scramble_type=0;
		RET_CODE dmx_state = RET_FAILURE;


		vdec_io_control(multi_decv_dev,VDEC_IO_GET_STATUS,(UINT32)&Param);
//!Shorten the time of change box 
		if(VDEC_DECODING==Param.uCurStatus)
		{
			while(!Param.uFirstPicShowed)
			{
					if(get_mv_cancel())
						return FALSE;
					osal_task_sleep(10);
					vdec_io_control(multi_decv_dev, VDEC_IO_GET_STATUS, (UINT32)&Param);
					counter++;

					//here all box have it's picture already,and the play box is play now, so we need not wait for a long time 
					if(counter ==l_time_for_first_pip+10)
					{
						IsPlayNormal=FALSE;
						break;
					} 
					if(counter>=(l_time_for_first_pip/2))
					{ 
							nim_get_lock((struct nim_device*)dev_get_by_id(HLD_DEV_TYPE_NIM, 0), &lock);
							if(lock == 0)
							{
								unlockTimes++;
							}
							else
								unlockTimes=0;
							if(unlockTimes>(l_time_for_first_pip/4))
							{
								MV_DEBUG("%s:leave with unlock>>Counter:%d\n",__FUNCTION__,counter);
								IsPlayNormal=FALSE;
								break;		
							}
					} 

					struct dmx_device *dmx;
					dmx = (struct dmx_device *)dev_get_by_id(HLD_DEV_TYPE_DMX, 0);
                    dmx_state = dmx_io_control(dmx, IS_AV_SCRAMBLED, (UINT32)&scramble_type);
                    // the channel is scrambled
                    if((RET_SUCCESS==dmx_state)
                        &&((scramble_type & (VDE_TS_SCRBL|VDE_PES_SCRBL | VDE_STR_INVALID)) != 0)
                                &&(counter>=l_time_for_first_pip))
					{
						MV_DEBUG("%s:leave with scrambled.>>Counter:%d\n",__FUNCTION__,counter);
						IsPlayNormal=FALSE;
						break;
					} 
					if(counter %(l_time_for_first_pip*2)==0&&counter>=l_time_for_first_pip)//reset qpsk
					{ 
						//cc_reset_qpsk(0);
						MV_DEBUG("MV___MW_SwitchPIPWin reset qpsk>>>>>>>>>%d>>>>>>>>.\n",counter);				
					} 

			}
			if(Param.uFirstPicShowed && IsPlayNormal)
			{
					PipInfo.full_screen_height=1080;
					PipInfo.full_screen_width=1920;
					PipInfo.left_x = l_MVinitPara.puBoxPosi[uCurrentActiveIndex].uX;
					PipInfo.left_y = l_MVinitPara.puBoxPosi[uCurrentActiveIndex].uY;
					PipInfo.window_width = l_MVinitPara.tPipSize.uWidth;
					PipInfo.window_height = l_MVinitPara.tPipSize.uHeight;
					vdec_stop(multi_decv_dev,FALSE,FALSE);
					vdec_io_control(multi_decv_dev, VDEC_IO_FILL_BG_VIDEO, (UINT32)&PipInfo);
					osal_task_sleep(50);//wait for the DE  switch buffer,avoid flash screen when change window

                    if(sys_ic_get_chip_id() == ALI_S3811)
					    vpo_ioctl(multi_vpo_dev, VPO_IO_UPDATE_GINGA, 1);
					MV_DEBUG("%s-->#Got the(%d,%d) box's picture,Counter=%d.\n",__FUNCTION__,PipInfo.left_x,PipInfo.left_y,counter);
			}
			else//no video data channel(no signal or scrambled etc) , fill black to the box
			{
				//to do...
				MV_DEBUG("%s-->#No video data channel,can't get the(%d,%d) box's picture,Counter=%d.\n",__FUNCTION__,PipInfo.left_x,PipInfo.left_y,counter);
			}
		}
		else //vdec not start, do nothing?
		{
			//to do...
			MV_DEBUG("%s-->#Vdec not start,can't get the(%d,%d) box's picture,Counter=%d.\n",__FUNCTION__,PipInfo.left_x,PipInfo.left_y,counter);
		}
		DrawBoxProcSuccess=TRUE;
		return TRUE;
}

BOOL GetBoxPlayStatus(void)
{
	if(!get_mv(LIBPUB_FLG_MV_BUSY))
		return TRUE;
	return FALSE;
}
void SetBoxPlayStatus(BOOL flag)
{
	BoxPlayOk=flag;
}
static RET_CODE MultiView_DrawOneBox(UINT16 uActiveIndex)
{
	//UINT32 uindex;
	UINT32 boxStatus;
	struct VDecPIPInfo  PIPInitInfo;
	UINT32 cmd = 0;


	if(hde_get_mode() != VIEW_MODE_MULTI)
	{
		MV_DEBUG("Alert!!! Not in multiview mode\n");	
		return RET_FAILURE;
	}
	
	DrawBoxProcSuccess=FALSE;
//!fill the last picture to the last box
	MV_StoreLastPicture();
	//cc_stop_channel(FALSE,0);
	sim_cc_stop_channel(cmd, l_mv_es[uCurrentActiveIndex], l_mv_dev_list[uCurrentActiveIndex]);

	
	if(DrawBoxProcSuccess)
	{
		//uindex=gMvpara.uProgInfo[uActiveIndex];
		boxStatus=BOX_PLAY_NORMAL;
		uCurrentActiveIndex = uActiveIndex;

		//1Switch to the special box	
		if(l_MVinitPara.callback!=NULL)
		{
			boxStatus=l_MVinitPara.callback(uActiveIndex);
		}
		//MultiView_Play_ActiveBox(&l_MVinitPara.tMPipBoxPosi[uActiveIndex], l_mv_es[uActiveIndex], l_mv_ft[uActiveIndex], l_mv_dev_list[uActiveIndex], boxStatus, &PIPInitInfo);
		MultiView_Play_ActiveBox(uActiveIndex, boxStatus, &PIPInitInfo);
		if(l_MVinitPara.callback!=NULL)
			(l_MVinitPara.callback)(uActiveIndex+BOX_FINISHED);
		return RET_SUCCESS;
	}
	else
	{
		MV_DEBUG("%s,DrawOneBox Process Busy!\n",__FUNCTION__);
	}
}
/* Implement Multiview Command */
static void mv_cmd_implement_wrapped(struct libpub_cmd *cmd)
{
	struct MultiViewPara *mvPara = NULL;
	int i;

	switch(cmd->cmd_type)
	{
	case LIBPUB_CMD_MV_ENTER:
		MV_DEBUG("A message to enter!.\n");
		MV_DEBUG("After Rcv MultiviewEnter Cmd. Address is 0x%x\n", cmd->para1);

		mvPara = (struct MultiViewPara*)cmd->para1;
		set_mv(LIBPUB_FLG_MV_BUSY);
		clear_mv(LIBPUB_FLG_MV_CANCEL);
		MultiView_Enter(cmd->cmd_bit, mvPara);
		clear_mv(LIBPUB_FLG_MV_BUSY | LIBPUB_FLG_MV_CANCEL);
 		break;
		
	case LIBPUB_CMD_MV_DRAWONEBOX:
		MV_DEBUG("A message to drawonebox!.\n");		
		set_mv(LIBPUB_FLG_MV_BUSY);
		clear_mv(LIBPUB_FLG_MV_CANCEL);
		MultiView_DrawOneBox((UINT16)(cmd->para1));
		clear_mv(LIBPUB_FLG_MV_BUSY | LIBPUB_FLG_MV_CANCEL);
 		break;
	case LIBPUB_CMD_MV_EXIT:	
		MV_DEBUG("A message to exit!.\n");		
		set_mv(LIBPUB_FLG_MV_BUSY);
		clear_mv(LIBPUB_FLG_MV_CANCEL);
		MultiView_Exit();
		clear_mv(LIBPUB_FLG_MV_ACTIVE | LIBPUB_FLG_MV_BUSY | LIBPUB_FLG_MV_CANCEL | LIBPUB_FLG_MV_EXIT);                    
 		break;
	default:
		ASSERT(0);
	}
}


/*******************************************************
* external API
********************************************************/
__ATTRIBUTE_REUSE_
/* API for Multiview Initialization: Register Command and Initialize Local Struct */
void mv_init(void)
{
	int i;
	BOOL ret_bool;
	ret_bool = libpub_cmd_handler_register(LIBPUB_CMD_MV,mv_cmd_implement_wrapped);
	if(!ret_bool)
	{
		MV_DEBUG("libpub_cmd_handler_register failed.\n");
	}
	ret_bool = libpub_overlay_cmd_register(LIBPUB_CMD_MV_ENTER);
	if(!ret_bool)
	{
		MV_DEBUG("libpub_overlay_cmd_register LIBPUB_CMD_MV_ENTER failed.\n");
	}
	ret_bool = libpub_overlay_cmd_register(LIBPUB_CMD_MV_DRAWONEBOX);
	if(!ret_bool)
	{
		MV_DEBUG("libpub_overlay_cmd_register LIBPUB_CMD_MV_DRAWONEBOX failed.\n");
	}
	ret_bool = libpub_overlay_cmd_register(LIBPUB_CMD_MV_EXIT);
	if(!ret_bool)
	{
		MV_DEBUG("libpub_overlay_cmd_register LIBPUB_CMD_MV_EXIT failed.\n");
	}

	for(i=0; i<MV_BOX_NUM; i++)
	{
		l_mv_es[i] = &(gMvpara.mv_param[i].es);
		l_mv_dev_list[i]= &(gMvpara.mv_param[i].device_list);
		l_mv_ft[i] = &(gMvpara.mv_param[i].ft);
	}
}

/* API for Wait Exit Multiview Flag */
BOOL get_mv_exit(void)
{
	return get_mv(LIBPUB_FLG_MV_EXIT);
}

/* API for Init Before Enter Multiview */
void UIMultiviewInit(struct MVInitPara *tMVinitPara, enum MVMode mvMode)
{
	int i,j;
	enum MVMode tmvMode = mvMode;
	UINT8 col = 0, row = 0;

	g_bPlayInSpecialWin = FALSE;
	MEMCPY(&g_MVinitPara, tMVinitPara, sizeof(struct MVInitPara));
	if(mvMode == MV_AUTO_BOX)
	{
		if(tMVinitPara->uBoxNum <= 9)
		{
			tmvMode = MV_9_BOX;
		}
		else if(tMVinitPara->uBoxNum > 9 || tMVinitPara->uBoxNum <= 16)
		{
			tmvMode = MV_16_BOX;
		}
		else if(tMVinitPara->uBoxNum > 16)
		{
			tmvMode = MV_25_BOX;
		}
	}
		
	switch(tmvMode)
	{
		case MV_4_BOX:
			col = 2, row = 2;
			break;
		case MV_9_BOX:
			col = 3, row = 3;
			break;
		case MV_16_BOX:
			col = 4, row = 4;
			break;
		case MV_25_BOX:
			col = 5, row = 5;
			break;
		case MV_4_1_BOX:
			break;
		case MV_5_1_BOX:
			break;
		case MV_12_1_BOX:
			break;
		default:
			ASSERT(FALSE);
	}
	
	if(g_MVinitPara.tPipSize.uWidth < 200)
	{
		uPrecision= 8;
	}
	else
	{
		uPrecision = 4;
	}
	
	l_dview_h_precision = (uPrecision > ((VDEC27_DVIEW_PRECISION >> 16) & 0xFF)) ? uPrecision : ((VDEC27_DVIEW_PRECISION >> 16) & 0xFF);
	l_dview_v_precision = (uPrecision > (VDEC27_DVIEW_PRECISION & 0xFF)) ? uPrecision : (VDEC27_DVIEW_PRECISION & 0xFF);

#ifndef VIDEO_SUPPORT_EXTRA_DVIEW_WINDOW
	if(l_dview_h_precision == 4)
	{
		for(j = 0; j < col; j++)
		{
			for(i = 0; i < row; i++)
			{
				g_MVinitPara.puBoxPosi[i + j * row].uX = 176 * i + g_MVinitPara.puBoxPosi[0].uX;
			}
		}
	}
	else
	{
		for(j = 0; j < col; j++)
		{
			for(i = 0; i < row; i++)
			{
				g_MVinitPara.puBoxPosi[i + j * row].uX = 80 * i + g_MVinitPara.puBoxPosi[0].uX;
				g_MVinitPara.puBoxPosi[i + j * row].uY = 72 * j + g_MVinitPara.puBoxPosi[0].uY;
			}
		}
	}		
#endif
	MV_DEBUG("UIMultiviewInit-----leave!.\n");
}

/* API for Extenstion Init Before Enter Multiview */
void UIMultiviewInitExt(struct MVInitPara *tMVinitPara, enum MVMode mvMode, BOOL bPlayInSpecialWin)
{
	UIMultiviewInit(tMVinitPara, mvMode);
	g_bPlayInSpecialWin = bPlayInSpecialWin;	
}

/* API for Enter Multiview */
void UIMultiviewEnter(struct MultiViewPara *mvPara)
{
	UINT32 flgptn;
	struct libpub_cmd cmd;   

	libpub_clear_message_queue();
	flgptn = LIBPUB_FLG_MV_ACTIVE;
	if(get_mv(LIBPUB_FLG_MV_BUSY))
	{
		flgptn |= LIBPUB_FLG_MV_CANCEL;
	}
	set_mv(flgptn);
	MEMCPY(&l_MVinitPara,&g_MVinitPara,sizeof(struct MVInitPara));
	
  	MEMSET(&cmd, 0, sizeof(struct libpub_cmd));
	cmd.cmd_type=LIBPUB_CMD_MV_ENTER;
	cmd.sync = 1;
	cmd.para1 = (UINT32)mvPara;
	while(libpub_send_cmd(&cmd,OSAL_WAIT_FOREVER_TIME) != SUCCESS);
	MV_DEBUG("Send MultiviewEnter Cmd Successfully!.\n");
	
	if(cmd.sync)
	{
		//!it will cause dead lock when press page shift button quickly
		//libpub_wait_cmd_finish(LIBPUB_FLG_MV_ENTER, OSAL_WAIT_FOREVER_TIME);
	}
		
	l_mv_status = MV_ACTIVE|MV_SCAN_SCREEN|MV_SCAN_BOX;
	MV_DEBUG("UIMultiviewEnter -----leave!.\n");
}

/* API for Draw One Special Box */
BOOL UIMultiviewDrawOneBox(UINT16 uActiveIndex)
{
	struct libpub_cmd cmd;
	UINT32 flgptn;
	UINT8 times=0;

	libpub_clear_message_queue();
	flgptn = LIBPUB_FLG_MV_ACTIVE;
	if(get_mv(LIBPUB_FLG_MV_BUSY))
	{
	    	flgptn |= LIBPUB_FLG_MV_CANCEL;
	}
	set_mv(flgptn);

	MEMSET(&cmd, 0, sizeof(struct libpub_cmd));
	cmd.cmd_type = LIBPUB_CMD_MV_DRAWONEBOX;
	cmd.para1 = uActiveIndex;
	
	libpub_send_cmd(&cmd, OSAL_WAIT_FOREVER_TIME);
	
	return TRUE;
}

/* API for Exit Multiview */
void UIMultiviewExit()
{
	UINT32 flgptn;
	struct libpub_cmd cmd;
	
	libpub_clear_message_queue();

	flgptn = LIBPUB_FLG_MV_ACTIVE  | LIBPUB_FLG_MV_EXIT;
	if(get_mv(LIBPUB_FLG_MV_BUSY))
	{
		flgptn |= LIBPUB_FLG_MV_CANCEL;
	}
	set_mv(flgptn);

	MEMSET(&cmd, 0, sizeof(struct libpub_cmd));
	cmd.cmd_type = LIBPUB_CMD_MV_EXIT;
	
	libpub_send_cmd(&cmd, OSAL_WAIT_FOREVER_TIME);
	
	while(get_mv(LIBPUB_FLG_MV_ACTIVE))
	{
		osal_task_sleep(10);	
	}
}

/* API for Get Multiview Status */
UINT8 UIMultiviewGetStatus(void)
{
	return	l_mv_status;
}

/* API for Wait Cancel Multiview Flag */
BOOL get_mv_cancel(void)
{
    	return get_mv(LIBPUB_FLG_MV_CANCEL);
}
